package top.ersredma.imagetoexcle;
         
import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
         
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
         
/**
  * 本类用于将图像转存至表格文件
  * 
  * @author ersredma
  * 
  */
public class ExcelUtil {
            public final static int MODEL_USER = 0;
            public final static int MODEL_64COLORS = 64;
            public final static int MODEL_2COLORS = 2;
            public final static int MODEL_FULLCOLORS = 3375;
         
            private XSSFCellStyle defuStyle;
            private Map<String, XSSFCellStyle> bigColorMap = null;
            private Map<String, String> userMap = null;
            private static Set<String> setRgb = null;
            private XSSFWorkbook workbook = null;
            private static int x = 15;
            private int overThreadnum = 0;
            private boolean isInnt = false;
            private boolean isOpenThread = false;
            private MainView view;
         
            public ExcelUtil() {
                this.workbook = new XSSFWorkbook();
                bigColorMap = new ConcurrentHashMap<String, XSSFCellStyle>(3375);
                defuStyle = workbook.createCellStyle();
                XSSFColor xc = new XSSFColor(new byte[] { (byte) 255, (byte) 255,
                        (byte) 255 });
                defuStyle.setFillForegroundColor(xc);
                defuStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
         
            }
         
            public ExcelUtil(int model, MainView view, boolean openThread) {
                this.workbook = new XSSFWorkbook();
                this.view = view;
                this.isOpenThread = openThread;
                defuStyle = workbook.createCellStyle();
                XSSFColor xc = new XSSFColor(new byte[] { (byte) 255, (byte) 255,
                        (byte) 255 });
                defuStyle.setFillForegroundColor(xc);
                defuStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
         
                if (model == MODEL_USER) {
                    // 自定义色，从表格导入
                    bigColorMap = new ConcurrentHashMap<String, XSSFCellStyle>();
                    x = 0;
                } else if (model == MODEL_2COLORS) {
                    // 黑白色
                    bigColorMap = new ConcurrentHashMap<String, XSSFCellStyle>(2);
                    x = -1;
                } else if (model == MODEL_FULLCOLORS) {
                    x = 15;
                    bigColorMap = new ConcurrentHashMap<String, XSSFCellStyle>(model);
                } else {
                    x = (int) Math.cbrt(model);
                    bigColorMap = new ConcurrentHashMap<String, XSSFCellStyle>(model);
                }
            }
         
            public static void main(String[] args) {
                long start = System.currentTimeMillis();
                // int[][][] grbs = ImageUtils.getImageGRB("D:\\imgs\\mm.jpg");
                ExcelUtil eu = new ExcelUtil();
                // eu.inntColorsForThread();
                eu.createColorStyles();
                // eu.writeToFile(grbs, "D:\\imgs",false);
         
                // eu.exportRgbsToExcelFor2007(grbs, "D:\\rgbs.xlsx");
                // eu.allColorToFile("D:\\allcolornew1.xlsx");
                // int size = getRgbSet(grbs);
                System.out.println("耗时(ms):" + (System.currentTimeMillis() - start));
            }
         
            /**
      * 获取工作表
      * 
      * @return 当前对象的工作薄
      */
            public XSSFWorkbook getWorkbook() {
                return this.workbook;
            }
         
            /**
      * 返回当前颜色初始化是否结束
      * 
      * @return
      */
            public boolean isInnt() {
                return isInnt;
            }
         
            /**
      * 将rgbs信息写入2007版表格的封装方法
      * 
      * @param rgbs
      *            out的rgb信息
      * @param outputFilePath
      *            文件输出路径
      */
            public void writeToFile(int[][][] rgbs, String outputFilePath,
                    boolean isColor) {
                while (!isInnt) {
                    try {
                        Thread.sleep(10000);
                        System.out.println("等待载入颜色信息");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                exportRgbToExcelFor2007(rgbs, outputFilePath, isColor);
            }
         
            /**
      * outrgb信息转存xlsx表格文件 （2007版）
      * 
      * @param rgbs
      *            out的rgb数组
      * @param outputFilePath
      *            输出路径
      * @param isColor
      */
            private void exportRgbToExcelFor2007(int[][][] rgbs, String outputFilePath,
                    boolean isColor) {
                try {
                    XSSFSheet sheet;
                    if (workbook.getSheet("out") == null) {
                        sheet = workbook.createSheet("out");
                    } else {
                        sheet = workbook.getSheet("out");
                    }
                    sheet.setDefaultColumnWidth(10000);
                    sheet.setDefaultRowHeightInPoints(4000f);
                    for (int i = 0; i < rgbs.length; i++) {
                        XSSFRow row = sheet.createRow(i);
                        for (int j = 0; j < rgbs[i].length; j++) {
                            XSSFCell cell = row.createCell(j);
                            String key = getKeyForStyleMap(rgbs[i][j]);
                            cell.setCellStyle(bigColorMap.get(key));
                            if (isColor) {
                                cell.setCellValue(key);
                            }
                        }
                    }
                    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
                    String Str = formatter.format(new Date());
         
                    // 5、输出
                    FileOutputStream out = new FileOutputStream(new File(outputFilePath
                            + "\\" + Str + ".xlsx"));
                    workbook.write(out);
                    out.close();
                    view.writeOver(outputFilePath + "\\" + Str + ".xlsx");
                    resetWorkbook(rgbs.length, rgbs[0].length);
         
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
         
            /**
      * 恢复工作薄到空白状态
      * 
      * @param x
      *            宽
      * @param y
      *            高
      */
            private void resetWorkbook(int x, int y) {
                /*XSSFSheet sheet = workbook.getSheet("out");
        for (int i = 0; i < x; i++) {
            XSSFRow row = sheet.createRow(i);
            for (int j = 0; j < y; j++) {
                XSSFCell cell = row.createCell(j);
                cell.setCellStyle(defuStyle);
            }
        }*/
                int index = workbook.getSheetIndex("out");
                workbook.removeSheetAt(index);
            }
         
            public void initColors() {
                new Thread(new Runnable() {
                    @Override
            public void run() {
                        createColorStyles();
                    }
                }).start();
                try {
                    while (!isInnt()) {
                        view.setInfo("正在初始化颜色，请等待完成后再开始导出！ " + overThreadnum + "/" + x);
                        TimeUnit.MILLISECONDS.sleep(1000);
         
                    }
                    TimeUnit.MILLISECONDS.sleep(1000);
                    view.setInfo("初始化颜色完成，可以导出！");
                } catch (InterruptedException e) {
                     
                }
         
            }
         
            /**
      * 创建所有的颜色并存入map中
      */
            public void createColorStyles() {
                if (x == 0) {
                    readConfigCreateStyles();
                    isInnt = true;
                } else if (x == -1) {
                    XSSFCellStyle blackStyle = workbook.createCellStyle();
                    XSSFColor black = new XSSFColor(Color.black);
                    blackStyle.setFillForegroundColor(black);
                    blackStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
                    XSSFCellStyle whiteStyle = workbook.createCellStyle();
                    XSSFColor white = new XSSFColor(Color.white);
                    whiteStyle.setFillForegroundColor(white);
                    whiteStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
                    bigColorMap.put("black", blackStyle);
                    bigColorMap.put("white", whiteStyle);
                    isInnt = true;
                } else {
                    if (!isOpenThread) {
                        for (int r = 0; r < x; r++) {
                            for (int g = 0; g < x; g++) {
                                for (int b = 0; b < x; b++) {
                                    XSSFCellStyle style = workbook.createCellStyle();
                                    XSSFColor xc = new XSSFColor(new byte[] {
                                            (byte) (r != (x - 1) ? r * (255 / (x - 1))
                                                    : 255),
                                            (byte) (g != (x - 1) ? g * (255 / (x - 1))
                                                    : 255),
                                            (byte) (b != (x - 1) ? b * (255 / (x - 1))
                                                    : 255) });
                                    style.setFillForegroundColor(xc);
                                    style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                                    StringBuilder sb = new StringBuilder();
                                    bigColorMap.put(sb.append(r).append(",").append(g)
                                            .append(",").append(b).toString(), style);
                                }
                            }
                            threadOver();
                        }
                    } else {
                        inntColorsForThread();
                    }
                }
                Thread.yield();
            }
         
            public void readConfigCreateStyles() {
                userMap = new HashMap<String, String>();
                BufferedReader sc=null;
                try {
                    sc=new BufferedReader(new FileReader(new File("config/user.color")));
                    String line=null;
                    while ((line=sc.readLine())!=null) {
                        if (!line.startsWith("*")) {
                            String[] sp = line.split(":");
                            XSSFCellStyle style = workbook.createCellStyle();
                            String[] rgbs = sp[0].split(",");
                            XSSFColor color = new XSSFColor(new Color(
                                    Integer.parseInt(rgbs[0]),
                                    Integer.parseInt(rgbs[1]),
                                    Integer.parseInt(rgbs[2])));
                            style.setFillForegroundColor(color);
                            style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                            userMap.put(sp[0], sp[1]);
                            bigColorMap.put(sp[1], style);
                        }
                    }
                    sc.close();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    view.setInfo("自定义颜色配置文件出错！");
                }
         
            }
            /**
      * 
      * @param rgb
      * @return 根据当前的rgb计算出的对应map的key
      */
            private String getKeyForStyleMap(int[] rgb) {
                if (x == 0) {
                    int tempNum = 1000;
                    String keyS = "";
                    for (String str : userMap.keySet()) {
                        String[] sp = str.split(",");
                        int x = Math.abs(rgb[0] - Integer.parseInt(sp[0]))
                                + Math.abs(rgb[1] - Integer.parseInt(sp[1]))
                                + Math.abs(rgb[2] - Integer.parseInt(sp[2]));
                        if (x < tempNum) {
                            tempNum = x;
                            keyS = str;
                        }
                    }
                    return userMap.get(keyS);
                } else if (x == -1) {
                    if (rgb[0] + rgb[1] + rgb[2] > 380) {
                        return "white";
                    } else {
                        return "black";
                    }
                } else {
                    int r = rgb[0] % (255 / (x - 1)) > (255 / (x - 1)) / 2 ? rgb[0]
                            / (255 / (x - 1)) + 1 : rgb[0] / (255 / (x - 1));
                    int g = rgb[1] % (255 / (x - 1)) > (255 / (x - 1)) / 2 ? rgb[1]
                            / (255 / (x - 1)) + 1 : rgb[1] / (255 / (x - 1));
                    int b = rgb[2] % (255 / (x - 1)) > (255 / (x - 1)) / 2 ? rgb[2]
                            / (255 / (x - 1)) + 1 : rgb[2] / (255 / (x - 1));
                    return new StringBuilder().append(r).append(",").append(g)
                            .append(",").append(b).toString();
                }
            }
         
            public int getRgbSet(int[][][] rgbs) {
                setRgb = new HashSet<String>();
                for (int i = 0; i < rgbs.length; i++) {
                    for (int j = 0; j < rgbs[i].length; j++) {
                        setRgb.add(new StringBuilder().append(rgbs[i][j][0])
                                .append(",").append(rgbs[i][j][1]).append(",")
                                .append(rgbs[i][j][2]).toString());
                    }
                }
                return setRgb.size();
            }
         
            public void allColorToFile(String outputFilePath) {
                while (!isInnt) {
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                XSSFSheet sheet = workbook.createSheet("out");
                sheet.setDefaultColumnWidth(1);
                sheet.setDefaultRowHeightInPoints(1);
                Set<String> keySet = bigColorMap.keySet();
                Set<String> treeSet = new TreeSet<>(keySet);
                int i = 0;
                int j = 0;
                XSSFRow row = null;
                for (String str : treeSet) {
                    if (i % 10 == 0) {
                        row = sheet.createRow(i / 10);
                        j = 0;
                    }
                    XSSFCell cell = row.createCell(j++);
                    cell.setCellStyle(bigColorMap.get(str));
                    cell.setCellValue(str);
                    i++;
                }
         
                // 5、输出
                FileOutputStream out;
                try {
                    out = new FileOutputStream(new File(outputFilePath));
                    workbook.write(out);
                    out.close();
         
                    sheet = workbook.getSheet("out");
                    i = 0;
                    j = 0;
                    row = null;
                    for (String str : treeSet) {
                        if (i % 10 == 0) {
                            row = sheet.createRow(i / 10);
                            j = 0;
                        }
                        XSSFCell cell = row.createCell(j++);
         
                        cell.setCellStyle(defuStyle);
                        cell.setCellValue("");
                        i++;
                    }
                    // workbook.close();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
         
            }
         
            private void inntColorsForThread() {
                for (int i = 0; i < 15; i++) {
                    InntColorsThread run = new InntColorsThread(i, this);
                    new Thread(run).start();
                }
            }
         
            public void addColors(Map<String, XSSFCellStyle> colorMap) {
                this.bigColorMap.putAll(colorMap);
                overThreadnum++;
                if (overThreadnum == 15) {
                    isInnt = true;
                }
            }
         
            public void addColor(String key, XSSFCellStyle colorStyle) {
                this.bigColorMap.put(key, colorStyle);
            }
         
            public void threadOver() {
                overThreadnum++;
                if (overThreadnum == x) {
                    isInnt = true;
                }
            }
         
            public int getOvers() {
                return overThreadnum;
            }
         
        }
